home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / fpkpas92.zip / SRCRTL.ZIP / RTL / DOS / SYSTEM.INC < prev    next >
Text File  |  1997-07-01  |  51KB  |  1,908 lines

  1. {****************************************************************************
  2.  
  3.                        Copyright (c) 1993,97 by
  4.                     Florian Klaempfl & Michael Spiegel
  5.  
  6.  ****************************************************************************}
  7.  
  8.  
  9. { betriebssystemunabhaengige Implementationen der Unit System }
  10.  
  11.     {$I SET.INC}
  12.  
  13.     type       
  14.        textbuf = array[0..127] of char;
  15.  
  16.        textrec = record
  17.           handle : word;
  18.           mode : word;
  19.           bufsize : word;
  20.           { private : word; PRIVATE is a key word }
  21.           { lets use that field for typed file    }
  22.           _private : word;
  23.           bufpos : word;
  24.           bufend : word;
  25.           bufptr : ^textbuf;
  26.           openfunc : pointer;
  27.           inoutfunc : pointer;
  28.           flushfunc : pointer;
  29.           closefunc : pointer;
  30.           userdata : array[1..16] of byte;
  31. {$ifdef linux}
  32.           name : string[255];
  33. {$else}
  34.           name : string[79];
  35. {$endif}
  36.           buffer : textbuf;
  37.        end;
  38.  
  39.     { don't call this routines direct }
  40.  
  41.     procedure help_constructor;
  42.  
  43.       begin
  44.          asm
  45. .globl HELP_CONSTRUCTOR_NE
  46. HELP_CONSTRUCTOR_NE:
  47. .globl HELP_CONSTRUCTOR
  48. HELP_CONSTRUCTOR:
  49.             { Einsprung ohne Prolog, da wir ESP vom Constructor brauchen }
  50.             { Stack (relativ zu %ebp):
  51.                 12 Self
  52.                 8 VMT-Adresse
  53.                 4 Hauptprogramm-Addr
  54.                 0 %ebp
  55.             }
  56.             { Self initialisieren? }
  57.             orl %esi,%esi
  58.             jne LHC_4
  59.             { Speicher anfordern, aber erst Register retten }
  60.             { Hilfsvariable }
  61.             subl $4,%esp
  62.             movl %esp,%esi
  63.             { Register retten }
  64.             pushal
  65.             { Speichergröße }
  66.             movl 8(%ebp),%eax
  67.             pushl (%eax)
  68.             pushl %esi
  69.             call GETMEM
  70.             popal
  71.             { Speicherbereich nach %esi }
  72.             movl (%esi),%esi
  73.             addl $4,%esp
  74.             { falls kein Speicher vorhanden fail() }
  75.             orl %esi,%esi
  76.             jz LHC_5
  77.             { set zero inside the object }
  78.             pushal
  79.             pushw $0
  80.             movl 8(%ebp),%eax
  81.             pushl (%eax)
  82.             pushl %esi
  83.             {                }
  84.             call L_FILL_OBJECT
  85.             popal
  86.             { init self for the constructor }
  87.             movl %esi,12(%ebp)
  88.          LHC_4:
  89.             { is there a VMT address ? }
  90.             movl 8(%ebp),%eax
  91.             orl %eax,%eax
  92.             jnz LHC_7
  93.             { falls der Konstruktor nichts macht, darf das Zero-Flag }
  94.             { nicht gesetzt sein, da sonst fail() "aufgerufen" wird }
  95.             incl %eax
  96.             ret
  97.          LHC_7:
  98.             movl %eax,(%esi)
  99.          LHC_5:
  100.             ret
  101.          end;
  102.       end;
  103.  
  104.     procedure help_fail;
  105.  
  106.       begin
  107.          asm
  108.          end;
  109.       end;
  110.  
  111.     procedure help_destructor;
  112.  
  113.       begin
  114.          asm
  115.             { Stack (relativ zu %ebp):
  116.                 12 Self
  117.                 8 VMT-Adresse
  118.                 4 Hauptprogramm-Addr
  119.                 0 %ebp
  120.             }
  121. .globl HELP_DESTRUCTOR_NE
  122. HELP_DESTRUCTOR_NE:
  123. .globl HELP_DESTRUCTOR
  124. HELP_DESTRUCTOR:
  125.             { temporäre Variable }
  126.             subl $4,%esp
  127.             movl %esp,%edi
  128.             pushal
  129.             { muß das Objekt gelöscht werden ? }
  130.             movl 8(%ebp),%eax
  131.             orl %eax,%eax
  132.             jz LHD_3
  133.             { ja, dann Größe aus SELF! laden }
  134.             movl 12(%ebp),%eax
  135.             { VMT-Zeiger (aus Self) nach %ebx }
  136.             movl (%eax),%ebx
  137.             { und Größe auf den Stack }
  138.             pushl (%ebx)
  139.             { SELF }
  140.             movl %eax,(%edi)
  141.             pushl %edi
  142.             call FREEMEM
  143.          LHD_3:
  144.             popal
  145.             addl $4,%esp
  146.             ret
  147.          end;
  148.       end;
  149.  
  150.     procedure dump_stack(bp : longint);
  151.  
  152.     function get_next_frame(bp : longint) : longint;
  153.  
  154.       begin
  155.          asm
  156.          movl bp,%eax
  157.          movl (%eax),%eax
  158.          movl %eax,__RESULT
  159.          end ['EAX'];
  160.       end;
  161.  
  162.     procedure dump_frame(addr : longint);
  163.       begin
  164.          {to be used by symify }
  165.          writeln('  0x',HexStr(addr,8));
  166.       end;
  167.  
  168.       function get_addr(BP : longint) : longint;
  169.  
  170.         begin
  171.            asm
  172.               movl BP,%eax
  173.               movl 4(%eax),%eax
  174.               movl %eax,__RESULT
  175.            end ['EAX'];
  176.         end;
  177.       var i, prevbp : longint;
  178.  
  179.       begin
  180.          prevbp:=bp-1;
  181.          i:=0;
  182.          while bp > prevbp do
  183.            begin
  184.               dump_frame(get_addr(bp));
  185.               i:=i+1;
  186.               if i>max_frame_dump then exit;
  187.               prevbp:=bp;
  188.               bp:=get_next_frame(bp);
  189.            end;
  190.       end;
  191.  
  192.     procedure runerror(w : word);
  193.  
  194.  
  195.       function get_addr : longint;
  196.  
  197.         begin
  198.            asm
  199.               movl (%ebp),%eax
  200.               movl 4(%eax),%eax
  201.               movl %eax,__RESULT
  202.            end;
  203.         end;
  204.  
  205.       function get_error_bp : longint;
  206.  
  207.         begin
  208.            asm
  209.               movl (%ebp),%eax {%ebp of run_error}
  210.               movl %eax,__RESULT
  211.            end ['EAX'];
  212.         end;
  213.  
  214.       begin
  215.          errorcode:=w;
  216.          erroraddr:=pointer(get_addr);
  217.          writeln('Run time error ',errorcode,' at 0x',hexstr(longint(erroraddr),8));
  218.          dump_stack(get_error_bp);
  219.          halt(errorcode);
  220.       end;
  221.  
  222.     procedure io1(addr : longint);[public,alias: 'IOCHECK'];
  223.  
  224.       var
  225.          l : longint;
  226.  
  227.       begin
  228.          { da IOCHECK direkt aufgerufen wird und später der Optimierer }
  229.          { vielleicht auch global Register zuweist               }
  230.          asm
  231.             pushal
  232.          end;
  233.          l:=ioresult;
  234.          if l<>0 then
  235.            begin
  236.               writeln('I/O-Error ',l,' at ',addr);
  237.               halt(1);
  238.            end;
  239.          asm
  240.             popal
  241.          end;
  242.       end;
  243.  
  244. {$S-}
  245.     procedure st1(stack_size : longint);[public,alias: 'STACKCHECK'];
  246.  
  247.       begin
  248.          { called when trying to get local stack }
  249.          { if the compiler directive $S is set   }
  250.          asm
  251.             movl stack_size,%ebx
  252.             movl %esp,%eax
  253.             subl %ebx,%eax
  254. {$ifdef SYSTEMDEBUG}
  255.             movl U_SYSTEM_LOWESTSTACK,%ebx
  256.             cmpl %eax,%ebx
  257.             jb   _is_not_lowest
  258.             movl %eax,U_SYSTEM_LOWESTSTACK
  259.             _is_not_lowest:
  260. {$endif SYSTEMDEBUG}
  261.             movl __stkbottom,%ebx
  262.             cmpl %eax,%ebx
  263.             jae  __short_on_stack
  264.             leave
  265.             ret  $4
  266.             __short_on_stack:
  267.          end['EAX','EBX'];
  268.          { this needs a local variable }
  269.          { so the function called itself !! }
  270.          { Writeln('low in stack ');}
  271.          RunError(202);
  272.       end;
  273. {no stack check in system }
  274.  
  275.     procedure re_overflow;[public,alias: 'RE_OVERFLOW'];
  276.  
  277.       var
  278.          addr : longint;
  279.  
  280.       begin
  281.          { write return address as overflow position }
  282.          asm
  283.             movl 4(%ebp),%edi
  284.             movl %edi,addr
  285.          end;
  286.          writeln('integer overflow at $',hexstr(addr,8));
  287.          writeln('Overflow at ',addr);
  288.          halt(1);
  289.       end;
  290.  
  291.     { kopiert Strings }
  292.     { Darf nie direkt aufgerufen werden, da  *** nicht ***  mit }
  293.     { einer Exceptionadresse auf dem Stack gerechnet wird }
  294.     { außerdem werden Parameter von links nach rechts erwartet!! }
  295.     procedure strcopy(dstr,sstr : pointer;len : longint);[public,alias: 'STRCOPY'];
  296.  
  297.       begin
  298.          asm
  299.             cld
  300.             movl 16(%ebp),%edi    // Parameter laden
  301.             movl 12(%ebp),%esi
  302.             movl 8(%ebp),%ecx
  303.             lodsb        // Laenge von Quelle laden
  304.             cmpb %cl,%al
  305.             jbe LM4
  306.             movb %cl,%al    // wenn laenger als max. Laenge des Ziel,
  307.                         // dann Quelle abschneiden
  308.          LM4:
  309.             movzbl %al,%eax
  310.             mov %eax,%ecx
  311.             stosb        // Länge speichern
  312.             shrl $2,%ecx     // Erst dwordweise kopieren
  313.             rep
  314.             movsl
  315.             movl %eax,%ecx     // ...und nun die restlichen Bytes
  316.             andl $3,%ecx
  317.             rep
  318.             movsb
  319.             leave        // eigenes Return, wegen anderem Stackframe
  320.             ret $12
  321.          end;
  322.       end;
  323.  
  324.     { verknüpft Strings }
  325.     { Darf nie direkt aufgerufen werden, da  *** nicht ***  mit }
  326.     { einer Exceptionadresse auf dem Stack gerechnet wird }
  327.     { haengt s2 an s1 an }
  328.     { außerdem werden Parameter von links nach rechts erwartet!! }
  329.     procedure strconcat(s1,s2 : pointer);[public,alias: 'STRCONCAT'];
  330.  
  331.       begin
  332.          asm
  333.         movl 12(%ebp),%edi    // Laenge des ersten Strings nach ECX
  334.         movb (%edi),%cl
  335.         movzbl %cl,%ecx
  336.         movl 12(%ebp),%edi  // Startadresse fuer den zweiten String
  337.                     // berechnen
  338.         lea 1(%edi,%ecx),%edi
  339.         negl %ecx        // Restplatz berechnen
  340.         addl $0xff,%ecx
  341.         movl 8(%ebp),%esi    // Laenge des zweiten Strings nach AL
  342.         lodsb
  343.             cmpb %cl,%al
  344.             jbe LM5
  345.             movb %cl,%al    // falls zu lang, dann abschneiden
  346.      LM5:
  347.         movb %al,%cl
  348.         movl 12(%ebp),%ebx
  349.         addb %cl,(%ebx)     // Resultatlaenge schreiben
  350.         movzbl %cl,%ecx
  351.             movl %ecx,%eax     // Laenge retten
  352.             shrl $2,%ecx     // Erst dwordweise kopieren
  353.             cld
  354.             rep
  355.             movsl
  356.             movl %eax,%ecx     // ...und nun die restlichen Bytes
  357.             andl $3,%ecx
  358.             rep
  359.             movsb
  360.             leave        // eigenes Return, wegen anderem Stackframe
  361.             ret $8
  362.          end ['EAX','EBX','ECX','EDI'];
  363.       end;
  364.  
  365.     { vergleicht Strings (Flags sind danach gesetzt }
  366.     { Darf nie direkt aufgerufen werden, da  *** nicht ***  mit }
  367.     { einer Exceptionadresse auf dem Stack gerechnet wird }
  368.     { außerdem werden Parameter von links nach rechts erwartet!! }
  369.  
  370.     procedure strcmp(dstr,sstr : pointer);[public,alias: 'STRCMP'];
  371.  
  372.       begin
  373.          asm
  374.             movl 12(%ebp),%esi
  375.             movl 8(%ebp),%edi
  376.             cld
  377.             lodsb        // Laenge des ersten Strings nach AL
  378.             movb (%edi),%ah    // Laenge des zweiten Strings nach AH
  379.             incl %edi
  380.             movb %al,%cl    // den kuerzeren String berechnen
  381.             cmpb %ah,%cl
  382.             jbe LSTRCONCAT1
  383.             movb %ah,%cl
  384.         LSTRCONCAT1:
  385.             orb %cl,%cl        // Laenge gleich 0 ?
  386.             jz LSTRCONCAT2
  387.             movzbl %cl,%ecx
  388.             rep            // Stringvergleich
  389.             cmpsb
  390.             jne LSTRCONCAT3    // Ende erreicht ?
  391.         LSTRCONCAT2:
  392.             cmpb %ah,%al    // dann Laengenvergleich
  393.         LSTRCONCAT3:
  394.             leave        // eigenes Return, wegen anderem Stackframe
  395.             ret $8
  396.          end;
  397.       end;
  398.  
  399.     function strpas(p : pchar) : string;
  400.  
  401.       begin
  402.          asm
  403.             cld
  404.             movl 12(%ebp),%edi
  405.             movl %edi,%esi               // Quelle
  406.             movl $0xffffffff,%ecx        // nach Ende suchen
  407.             xorb %al,%al
  408.             repne
  409.             scasb
  410.             notl %ecx
  411.             decl %ecx
  412.             movl 8(%ebp),%edi          //  Ziel neu laden
  413.             movb %cl,%al
  414.             stosb
  415.             rep
  416.             movsb
  417.          end ['ECX','EAX','ESI','EDI'];
  418.       end;
  419.  
  420.     function strlen(p : pchar) : longint;
  421.  
  422.       begin
  423.          asm
  424.             cld
  425.             movl 8(%ebp),%edi
  426.             movl $0xffffffff,%ecx
  427.             xorb %al,%al
  428.             repne
  429.             scasb
  430.             movl $0xfffffffe,%eax
  431.             subl %ecx,%eax
  432.             leave
  433.             ret $4
  434.          end ['EDI','ECX','EAX'];
  435.       end;
  436.  
  437.     procedure move(var source;var dest;count : longint);
  438.  
  439.       { count : EBP+16 }
  440.  
  441.       var
  442.          sp,dp : pointer;
  443.  
  444.       { sp : EBP-4 }
  445.       { dp : EBP-8 }
  446.  
  447.       begin
  448.          if count=0 then
  449.            exit;
  450.          sp:=@source;
  451.          dp:=@dest;
  452.          if sp>dp then
  453.            asm
  454.               cld
  455.               movl 16(%ebp),%ecx
  456.               movl -4(%ebp),%esi
  457.               movl -8(%ebp),%edi
  458.               movl %ecx,%eax
  459.               shrl $2,%ecx
  460.               rep
  461.               movsl
  462.               movl %eax,%ecx
  463.               andl $3,%ecx
  464.               rep
  465.               movsb
  466.            end ['ESI','EDI','ECX','EAX']
  467.          else if sp<dp then
  468.            { vorsichtshalber rückwärts kopieren: }
  469.            asm
  470.               std
  471.               movl 16(%ebp),%ecx
  472.               movl -4(%ebp),%esi
  473.               movl -8(%ebp),%edi
  474.               addl %ecx,%esi
  475.               addl %ecx,%edi
  476.               movl %ecx,%eax
  477.               andl $3,%ecx
  478.               orl %ecx,%ecx
  479.               jz LMOVE1
  480.               { ESI und EDI müssen erst richtig berechnet werden }
  481.               decl %esi
  482.               decl %edi
  483.               rep
  484.               movsb
  485.               incl %esi
  486.               incl %edi
  487.            LMOVE1:
  488.               subl $4,%esi
  489.               subl $4,%edi
  490.               movl %eax,%ecx
  491.               shrl $2,%ecx
  492.               rep
  493.               movsl
  494.               cld
  495.            end ['ESI','EDI','ECX'];
  496.       end;
  497.  
  498.     procedure fillchar(var x;count : longint;value : byte);[alias: 'L_FILL_OBJECT'];
  499.  
  500.       begin
  501.          asm
  502.             movl 8(%ebp),%edi
  503.             movl 12(%ebp),%ecx
  504.             movb 16(%ebp),%dl
  505.             // EAX mit 4fachem Byte füllen:
  506.             movb %dl,%dh
  507.             movw %dx,%ax
  508.             shll $16,%eax
  509.             movw %dx,%ax
  510.             movl %ecx,%edx
  511.             shrl $2,%ecx
  512.             cld
  513.             rep
  514.             stosl
  515.             movl %edx,%ecx
  516.             andl $3,%ecx
  517.             rep
  518.             stosb
  519.          end ['EAX','ECX','EDX','EDI'];
  520.       end;
  521.  
  522.     procedure fillchar(var x;count : longint;value : char);
  523.  
  524.       begin
  525.          fillchar(x,count,byte(value));
  526.       end;
  527.  
  528.     procedure fillword(var x;count : longint;value : word);
  529.  
  530.       begin
  531.          asm
  532.             movl 8(%ebp),%edi
  533.             movl 12(%ebp),%ecx
  534.             movw 16(%ebp),%dx
  535.             // EAX mit 4fachem Byte füllen:
  536.             movw %dx,%ax
  537.             shll $16,%eax
  538.             movw %dx,%ax
  539.             movl %ecx,%edx
  540.             shrl $1,%ecx
  541.             cld
  542.             rep
  543.             stosl
  544.             movl %edx,%ecx
  545.             andl $1,%ecx
  546.             rep
  547.             stosw
  548.          end ['EAX','ECX','EDX','EDI'];
  549.       end;
  550.  
  551. {$I INNR.INC}
  552.  
  553.     function lo(w : word) : byte;[INTERNPROC: in_lo_word];
  554.     function hi(w : word) : byte;[INTERNPROC: in_hi_word];
  555.     function lo(i : integer) : byte;[INTERNPROC: in_lo_word];
  556.     function hi(i : integer) : byte;[INTERNPROC: in_hi_word];
  557.  
  558.     function lo(l : longint) : word;[INTERNPROC: in_lo_long];
  559.     function hi(l : longint) : word;[INTERNPROC: in_hi_long];
  560.  
  561.     function ord(c : char) : byte;[INTERNPROC: in_ord_char];
  562.  
  563.     { not fast, but easy }
  564.     function ord(b : boolean) : byte;
  565.     
  566.       begin
  567.          ord:=byte(b);
  568.       end;
  569.       
  570.     function chr(b : byte) : char;[INTERNPROC: in_chr_byte];
  571.  
  572.     function length(s : string) : byte;[INTERNPROC: in_length_string];
  573.  
  574.     procedure inc(var i : longint);[INTERNPROC: in_inc_dword];
  575.     procedure inc(var i : integer);[INTERNPROC: in_inc_word];
  576.     procedure inc(var i : word);[INTERNPROC: in_inc_word];
  577.     procedure inc(var i : shortint);[INTERNPROC: in_inc_byte];
  578.     procedure inc(var i : byte);[INTERNPROC: in_inc_byte];
  579.     procedure dec(var i : longint);[INTERNPROC: in_dec_dword];
  580.     procedure dec(var i : integer);[INTERNPROC: in_dec_word];
  581.     procedure dec(var i : word);[INTERNPROC: in_dec_word];
  582.     procedure dec(var i : shortint);[INTERNPROC: in_dec_byte];
  583.     procedure dec(var i : byte);[INTERNPROC: in_dec_byte];
  584.  
  585.     procedure inc(var i : longint;a : longint);
  586.  
  587.       begin
  588.          i:=i+a;
  589.       end;
  590.  
  591.     procedure dec(var i : longint;a : longint);
  592.  
  593.       begin
  594.          i:=i-a;
  595.       end;
  596.  
  597.     procedure dec(var i : word;a : longint);
  598.  
  599.       begin
  600.          i:=i-a;
  601.       end;
  602.  
  603.     procedure inc(var i : word;a : longint);
  604.  
  605.       begin
  606.          i:=i+a;
  607.       end;
  608.  
  609.     procedure dec(var i : integer;a : longint);
  610.  
  611.       begin
  612.          i:=i-a;
  613.       end;
  614.  
  615.     procedure inc(var i : integer;a : longint);
  616.  
  617.       begin
  618.          i:=i+a;
  619.       end;
  620.  
  621.     procedure dec(var i : byte;a : longint);
  622.  
  623.       begin
  624.          i:=i-a;
  625.       end;
  626.  
  627.     procedure inc(var i : byte;a : longint);
  628.  
  629.       begin
  630.          i:=i+a;
  631.       end;
  632.  
  633.     procedure dec(var i : shortint;a : longint);
  634.  
  635.       begin
  636.          i:=i-a;
  637.       end;
  638.  
  639.     procedure inc(var i : shortint;a : longint);
  640.  
  641.       begin
  642.          i:=i+a;
  643.       end;
  644.  
  645.     function abs(l : longint) : longint;
  646.  
  647.       begin
  648.          asm
  649.             movl 8(%ebp),%eax
  650.             orl %eax,%eax
  651.             jns LMABS1
  652.             negl %eax
  653.          LMABS1:
  654.             leave
  655.             ret $4
  656.          end ['EAX'];
  657.       end;
  658.  
  659.     function odd(l : longint) : boolean;
  660.  
  661.       begin
  662.         asm
  663.            movl 8(%ebp),%eax
  664.            andl $1,%eax
  665.            setnz %al
  666.            leave
  667.            ret $4
  668.         end ['EAX'];
  669.       end;
  670.  
  671.     function sqr(l : longint) : longint;
  672.  
  673.       begin
  674.          asm
  675.             movl 8(%ebp),%eax
  676.             imull %eax,%eax
  677.             leave
  678.             ret $4
  679.          end ['EAX'];
  680.       end;
  681.  
  682.     {$I MATH.INC}
  683.  
  684.     procedure str(l : longint;var s : string);
  685.  
  686.       var
  687.          buffer : array[0..11] of byte;
  688.  
  689.       begin
  690.          { Workaround: }
  691.          if l=$80000000 then
  692.            begin
  693.               s:='-2147483648';
  694.               exit;
  695.            end;
  696.          asm
  697.             movl 8(%ebp),%eax        // Integer laden
  698.             movl 12(%ebp),%edi        // Stringadresse laden
  699.             xorl %ecx,%ecx        // Stringlaenge=0
  700.             xorl %ebx,%ebx        // Bufferlaenge=0
  701.             movl $0x0a,%esi        // 10 als Konstante zum Dividieren laden
  702.             testl $0x80000000,%eax    // vorzeichenbehaftet
  703.             jz LM2
  704.             neg %eax
  705.             movb $0x2d,1(%edi)      // '-' in String kopieren
  706.             incl %ecx
  707.          LM2:
  708.             cdq
  709.             idivl %esi,%eax
  710.             addb $0x30,%dl        // Rest in ASCII umrechnen
  711.             movb %dl,-12(%ebp,%ebx)
  712.             incl %ebx
  713.             cmpl $0,%eax
  714.             jnz LM2
  715.                             // String umkopieren
  716.          LM3:
  717.             movb -13(%ebp,%ebx),%al     // -13 da EBX erst spaeter
  718.                                 // dekremiert wird (spart Vergleich)
  719.             movb %al,1(%edi,%ecx)
  720.             incl %ecx
  721.             decl %ebx
  722.             jnz LM3
  723.             movb %cl,(%edi)        // Stringlaenge kopieren
  724.          end;
  725.       end;
  726.  
  727.    procedure str(i : integer;var s : string);
  728.  
  729.      begin
  730.         str(longint(i),s);
  731.      end;
  732.         
  733.    procedure str(si : shortint;var s : string);
  734.    
  735.      begin
  736.         str(longint(si),s);
  737.      end;
  738.      
  739.    procedure str(b : byte;var s : string);
  740.    
  741.      begin
  742.         str(longint(b),s);
  743.      end;
  744.      
  745.    procedure str(w : word;var s : string);
  746.    
  747.      begin
  748.         str(longint(w),s);
  749.      end;
  750.  
  751.    { weder besonders genau noch schnell, aber solide und leicht verständlich }
  752.  
  753.     procedure val(const s : string;var d : double;var code : word);
  754.  
  755.       var
  756.          { faster on a pentium }
  757.          esign,sign : double;
  758.  
  759.          i : longint;
  760.          exponent : longint;
  761.          flags : byte;
  762.          hd : double;
  763.  
  764.       begin
  765.          d:=0;
  766.          code:=1;
  767.          exponent:=0;
  768.          esign:=1;
  769.          flags:=0;
  770.          sign:=1;
  771.          while (s[code]=' ') or (s[code]=#9) do
  772.            inc(code);
  773.          if s[code]='+' then
  774.            inc(code)
  775.          else if s[code]='-' then
  776.            begin
  777.               sign:=-1.0;
  778.               inc(code);
  779.            end;
  780.          while (s[code]>='0') and (s[code]<='9') and (length(s)>=code) do
  781.            begin
  782.               { Vorkomma gelesen }
  783.               flags:=flags or 1;
  784.               d:=d*10;
  785.               d:=d+(ord(s[code])-ord('0'));
  786.               inc(code);
  787.            end;
  788.          { Kommastellen ? }
  789.          if (s[code]='.') and (length(s)>=code) then
  790.            begin
  791.               hd:=0.1;
  792.               inc(code);
  793.               { nach einem "Komma" muß eine Ziffer folgen }
  794.               if not((s[code]>='0') and (s[code]<='9')) or (length(s)<code) then
  795.                 begin
  796.                    d:=0.0;
  797.                    exit;
  798.                 end;
  799.               while (s[code]>='0') and (s[code]<='9') and (length(s)>=code) do
  800.                 begin
  801.                    { Nackkomma gelesen }
  802.                    flags:=flags or 2;
  803.                    d:=d+hd*(ord(s[code])-ord('0'));
  804.                    hd:=hd/10.0;
  805.                    inc(code);
  806.                 end;
  807.            end;
  808.          { weder Vorkomma- noch Nachkommastellen, dann abbrechen }
  809.          if flags=0 then
  810.            begin
  811.               d:=0.0;
  812.               exit;
  813.            end;
  814.          { Exponent ? }
  815.          if (upcase(s[code])='E') and (length(s)>=code) then
  816.            begin
  817.               inc(code);
  818.               if s[code]='+' then
  819.                 inc(code)
  820.               else if s[code]='-' then
  821.                 begin
  822.                    esign:=-1;
  823.                    inc(code);
  824.                 end;
  825.               if not((s[code]>='0') and (s[code]<='9')) or (length(s)<code) then
  826.                 begin
  827.                    d:=0.0;
  828.                    exit;
  829.                 end;
  830.               while (s[code]>='0') and (s[code]<='9') and (length(s)>=code) do
  831.                 begin
  832.                    exponent:=exponent*10;
  833.                    exponent:=exponent+ord(s[code])-ord('0');
  834.                    inc(code);
  835.                 end;
  836.            end;
  837.          { nun noch Exponent einrechnen }
  838.          if esign>0 then
  839.            for i:=1 to exponent do
  840.              d:=d*10
  841.          else
  842.            for i:=1 to exponent do
  843.              d:=d/10;
  844.          { nicht alle Zeichen gelesen ? }
  845.          if length(s)>=code then
  846.            begin
  847.               d:=0.0;
  848.               exit;
  849.            end;
  850.          { evalute sign }
  851.          d:=d*sign;
  852.          { success ! }
  853.          code:=0;
  854.       end;
  855.  
  856.     procedure val(const s : string;var b : byte);
  857.  
  858.       var
  859.          l : longint;
  860.  
  861.       begin
  862.          val(s,l);
  863.          b:=l;
  864.       end;
  865.  
  866.     procedure val(const s : string;var b : byte;var code : word);
  867.  
  868.       var
  869.          l : longint;
  870.  
  871.       begin
  872.          val(s,l,code);
  873.          b:=l;
  874.       end;
  875.  
  876.     procedure val(const s : string;var v : longint;var code : word);
  877.  
  878.       var
  879.          i : byte;
  880.          u : byte;
  881.          negativ : boolean;
  882.  
  883.       begin
  884.          negativ := false;
  885.          code := 1;
  886.          u := 0;
  887.          v := 0;
  888.          case s[1] of
  889.             '-' : begin
  890.                      negativ := true;
  891.                      code := 2;
  892.                   end;
  893.             '+' : code := 2;
  894.          end;
  895.          case s[code] of
  896.             '$' : begin
  897.                      i := 16;
  898.                      inc (code);
  899.                      while s[code] = #48 do inc (code);
  900.                      if ord (s[0]) - code > 7 then
  901.                         begin
  902.                            inc (code,8);
  903.                            exit;
  904.                         end;
  905.                   end;
  906.             '%' : begin
  907.                      i := 2;
  908.                      inc (code);
  909.                   end
  910.             else i := 10;
  911.          end;
  912.          u := 0;
  913.          v := 0;
  914.          while chr (code) <= s[0] do
  915.            begin
  916.               case s[code] of
  917.                  #48..#57  : u := ord (s[code]) - 48;
  918.                  #65..#70  : u := ord (s[code]) - 55;
  919.                  #97..#104 : u := ord (s[code]) - 87
  920.                  else u := 16;
  921.               end;
  922.               if (2147483647 - v*i < u) and ((i = 10) or (i = 2)) then u := 16;
  923.               if u >= i then
  924.                 begin
  925.                    v := 0;
  926.                    exit;
  927.                 end;
  928.                v := (v*i + u);
  929.                inc (code);
  930.             end;
  931.          code := 0;
  932.          if negativ then v := 0-v;
  933.       end;
  934.  
  935.     procedure val(const s : string;var v : longint);
  936.  
  937.      var
  938.         code : word;
  939.  
  940.      begin
  941.         val (s,v,code);
  942.      end;
  943.  
  944.     {$I real2str.inc}
  945.  
  946.     procedure str(d : double;var s : string);
  947.  
  948.       begin
  949.          str_real(-1,d,s);
  950.       end;
  951.  
  952.     var
  953.        randseed : longint;
  954.  
  955.     function random(l : longint) : longint;
  956.  
  957.       begin
  958.          randseed:=randseed*134775813+1;
  959.          random:=abs(randseed mod l);
  960.       end;
  961.  
  962.     { don't call this direct, the call is generated by the compiler }
  963.     procedure do_exit;[public,alias: '__EXIT'];
  964.  
  965.       begin
  966.          while exitproc<>nil do
  967.            begin
  968. {$ifdef DOS}
  969.               asm
  970.                  movl U_SYSTEM_EXITPROC,%eax
  971.                  call %eax
  972.               end;
  973. {$endif}
  974. {$ifdef OS2}
  975.               asm
  976.                  movl U_SYSOS2_EXITPROC,%eax
  977.                  call %eax
  978.               end;
  979. {$endif}
  980. {$ifdef LINUX}
  981.               asm
  982.                  movl U_SYSLINUX_EXITPROC,%eax
  983.                  call %eax
  984.               end;
  985. {$endif}
  986.            end;
  987.      end;
  988.  
  989. {****************************************************************************
  990.                     subroutines for file management
  991.  ****************************************************************************}
  992.         
  993.     type
  994.        filerec = record
  995.           handle : word;
  996.           mode : word;
  997.           recsize : word;
  998.           _private : array[1..26] of byte;
  999.           userdata : array[1..16] of byte;
  1000.           name : string[79];
  1001.        end;
  1002. {$IfNDef GO32V2}
  1003.     procedure doswrite(h,addr,len : longint);forward;
  1004.     function dosread(h,addr,len : longint) : longint;forward;
  1005. {$EndIf GO32V2}
  1006.     procedure fileinoutfunc(var f : textrec);
  1007.  
  1008.       begin
  1009.          if f.mode=fmoutput then
  1010.            begin
  1011.               doswrite(f.handle,longint(f.bufptr),f.bufpos);
  1012.            end
  1013.          else if f.mode=fminput then
  1014.            begin
  1015.               f.bufend:=dosread(f.handle,longint(f.bufptr),f.bufsize);
  1016.            end
  1017.          else halt(100);
  1018.          f.bufpos:=0;
  1019.       end;
  1020.  
  1021.     type
  1022.         dateifunc = procedure(var t : textrec);
  1023.  
  1024.     procedure fileopenfunc(var f : textrec);forward;
  1025.  
  1026.     procedure assign(var t : text;const s : string);
  1027.  
  1028.       begin
  1029.          textrec(t).handle:=$ffff;
  1030.          textrec(t).mode:=fmclosed;
  1031.          textrec(t).bufsize:=128;
  1032.          textrec(t).bufpos:=0;
  1033.          textrec(t).bufend:=0;
  1034.          textrec(t).bufptr:=@textrec(t).buffer;
  1035.          textrec(t).name:=s;
  1036.          textrec(t).openfunc:=@fileopenfunc;
  1037.       end;
  1038.  
  1039.     procedure assign(var f : file;const name : string);
  1040.  
  1041.       begin
  1042.          filerec(f).name:=name;
  1043.          filerec(f).mode:=fmclosed;
  1044.          filerec(f).handle:=$ffff;
  1045.          filerec(f).recsize:=$ffff;
  1046.       end;
  1047.  
  1048. {$ifdef typedfile }
  1049.     procedure assign(var f : typedfile;const name : string);
  1050.  
  1051.       begin
  1052.          filerec(f).name:=name;
  1053.          filerec(f).mode:=fmclosed;
  1054.          filerec(f).handle:=$ffff;
  1055.          { here we should insert the size of the type }
  1056.          { but how can we do that                     }
  1057.          filerec(f).recsize:=$ffff;
  1058.       end;
  1059. {$endif}
  1060.     procedure rewrite(var t : text);[iocheck];
  1061.  
  1062.       begin
  1063.          textrec(t).mode:=fmoutput;
  1064.          dateifunc(textrec(t).openfunc)(textrec(t));
  1065.       end;
  1066.  
  1067.     procedure reset(var t : text);[iocheck];
  1068.  
  1069.       begin
  1070.          textrec(t).mode:=fminput;
  1071.          dateifunc(textrec(t).openfunc)(textrec(t));
  1072.       end;
  1073.  
  1074.     procedure append(var t : text);[iocheck];
  1075.  
  1076.       begin
  1077.          textrec(t).mode:=fmappend;
  1078.          dateifunc(textrec(t).openfunc)(textrec(t));
  1079.       end;
  1080.  
  1081.     procedure w(len : longint;var f : textrec;var s : string);[public,alias: 'WRITE_TEXT_STRING'];
  1082.  
  1083.       var
  1084.          hbytes,pos,copybytes : longint;
  1085.          hs : string;
  1086.  
  1087.       begin
  1088.          if f.mode<>fmoutput then
  1089.            exit;
  1090.          copybytes:=length(s);
  1091.          
  1092.          if len>copybytes then
  1093.            begin
  1094.               hs:=space(len-copybytes);
  1095.               w(0,f,hs);
  1096.           end;        
  1097.          pos:=1;
  1098.          hbytes:=f.bufsize-f.bufpos;
  1099.  
  1100.          { wenn überhaupt kein Platz, dann ein flush durchführen }
  1101.          if hbytes=0 then
  1102.            dateifunc(f.flushfunc)(f);
  1103.          
  1104.          while copybytes>hbytes do
  1105.            begin
  1106.               move(s[pos],f.buffer[f.bufpos],hbytes);
  1107.               f.bufpos:=f.bufpos+hbytes;
  1108.               dec(copybytes,hbytes);
  1109.               inc(pos,hbytes);
  1110.               dateifunc(f.inoutfunc)(f);
  1111.               hbytes:=f.bufsize-f.bufpos;
  1112.            end;
  1113.          move(s[pos],f.buffer[f.bufpos],copybytes);
  1114.          f.bufpos:=f.bufpos+copybytes;  
  1115.       end;
  1116.  
  1117.     type
  1118.        array00 = array[0..0] of char;
  1119.  
  1120.     procedure w(len : longint;var f : textrec;const p : array00);[public,alias: 'WRITE_TEXT_PCHAR_AS_ARRAY'];
  1121.  
  1122.       var
  1123.          hbytes,pos,copybytes : longint;
  1124.          hs : string;
  1125.  
  1126.       begin
  1127.          if f.mode<>fmoutput then
  1128.            exit;
  1129.          copybytes:=strlen(p);
  1130.          if len>copybytes then
  1131.            begin
  1132.               hs:=space(len-copybytes);
  1133.               w(0,f,hs);
  1134.            end;
  1135.          pos:=0;
  1136.          hbytes:=f.bufsize-f.bufpos;
  1137.  
  1138.          { wenn überhaupt kein Platz, dann ein flush durchführen }
  1139.          if hbytes=0 then
  1140.            dateifunc(f.flushfunc)(f);
  1141.  
  1142.          while copybytes>hbytes do
  1143.            begin
  1144.               move(p[pos],f.buffer[f.bufpos],hbytes);
  1145.               f.bufpos:=f.bufpos+hbytes;
  1146.               dec(copybytes,hbytes);
  1147.               inc(pos,hbytes);
  1148.               dateifunc(f.inoutfunc)(f);
  1149.               hbytes:=f.bufsize-f.bufpos;
  1150.            end;
  1151.          move(p[pos],f.buffer[f.bufpos],copybytes);
  1152.          f.bufpos:=f.bufpos+copybytes;
  1153.       end;
  1154.  
  1155.     procedure wa(len : longint;var f : textrec;p : pchar);[public,alias: 'WRITE_TEXT_PCHAR_AS_POINTER'];
  1156.  
  1157.       begin
  1158.          w(len,f,p);
  1159.       end;
  1160.  
  1161.     procedure f1;[public,alias: 'FLUSH_STDOUT'];
  1162.  
  1163.       begin
  1164.          asm
  1165.             pushal
  1166.          end;
  1167.          dateifunc(textrec(output).flushfunc)(textrec(output));
  1168.          asm
  1169.             popal
  1170.          end;
  1171.       end;
  1172.  
  1173.     procedure flush(var t : text);[iocheck];
  1174.  
  1175.       begin
  1176.          if textrec(t).mode<>fmoutput then
  1177.            exit;
  1178.          dateifunc(textrec(t).flushfunc)(textrec(t));
  1179.       end;
  1180.  
  1181.     procedure doserase(p : pchar);forward;
  1182.     procedure dosrename(p1,p2 : pchar);forward;
  1183.  
  1184.     procedure erase(var t : text);[iocheck];
  1185.  
  1186.       var
  1187.          b : array[0..79] of char;
  1188.  
  1189.       begin
  1190.          if textrec(t).mode=fmclosed then
  1191.            begin
  1192.               move(textrec(t).name[1],b,length(textrec(t).name));
  1193.               b[length(textrec(t).name)]:=#0;
  1194.               doserase(b);
  1195.            end;
  1196.       end;
  1197.  
  1198.     procedure erase(var f : file);[iocheck];
  1199.  
  1200.       var
  1201.          b : array[0..79] of char;
  1202.  
  1203.       begin
  1204.          if filerec(f).mode=fmclosed then
  1205.            begin
  1206.               move(filerec(f).name[1],b,length(filerec(f).name));
  1207.               b[length(filerec(f).name)]:=#0;
  1208.               doserase(b);
  1209.            end;
  1210.       end;
  1211.  
  1212.     procedure rename(var f : file;const s : string);[iocheck];
  1213.  
  1214.       var
  1215.          b1,b2 : array[0..79] of char;
  1216.  
  1217.       begin
  1218.          if filerec(f).mode=fmclosed then
  1219.            begin
  1220.               move(filerec(f).name[1],b1,length(filerec(f).name));
  1221.               b1[length(filerec(f).name)]:=#0;
  1222.               move(s[1],b2,length(s));
  1223.               b2[length(s)]:=#0;
  1224.               dosrename(b1,b2);
  1225.               filerec(f).name:=s;
  1226.            end;
  1227.       end;
  1228.  
  1229.     procedure rename(var t : text;const s : string);[iocheck];
  1230.  
  1231.       var
  1232.          b1,b2 : array[0..79] of char;
  1233.  
  1234.       begin
  1235.          if textrec(t).mode=fmclosed then
  1236.            begin
  1237.               move(textrec(t).name[1],b1,length(textrec(t).name));
  1238.               b1[length(textrec(t).name)]:=#0;
  1239.               move(s[1],b2,length(s));
  1240.               b2[length(s)]:=#0;
  1241.               dosrename(b1,b2);
  1242.               textrec(t).name:=s;
  1243.            end;
  1244.       end;
  1245.  
  1246.     procedure w(len : longint;var t : textrec;l : longint);[public,alias: 'WRITE_TEXT_LONGINT'];
  1247.  
  1248.       var
  1249.          s : string;
  1250.  
  1251.       begin
  1252.          str(l,s);
  1253.          w(len,t,s);
  1254.       end;
  1255.       
  1256.     procedure w(fixkomma,len : longint;var t : textrec;r : real);[public,alias: 'WRITE_TEXT_REAL'];
  1257.  
  1258.       var
  1259.          s : string;
  1260.  
  1261.       begin
  1262.          str_real(fixkomma,r,s);
  1263.          w(len,t,s);
  1264.       end;
  1265.  
  1266.     { heißt wc, damit der Compiler keinen rekursiven Aufruf erzeugt }
  1267.  
  1268.     procedure wc(len : longint;var t : textrec;c : char);[public,alias: 'WRITE_TEXT_CHAR'];
  1269.     
  1270.       var
  1271.          hs : string;
  1272.  
  1273.       begin
  1274.          if t.mode<>fmoutput then
  1275.            exit;
  1276.            
  1277.          if len>1 then
  1278.            begin
  1279.               hs:=space(len-1);
  1280.               w(0,t,hs);
  1281.            end;
  1282.  
  1283.          if t.bufpos+1>=t.bufsize then
  1284.            dateifunc(t.flushfunc)(t);
  1285.          t.buffer[t.bufpos]:=c;
  1286.          inc(t.bufpos);
  1287.       end;
  1288.  
  1289.     procedure r(var f : textrec);[public,alias: 'READLN_TEXT'];
  1290.  
  1291.       begin
  1292.          { file must be opened for reading }
  1293.          if f.mode<>fminput then
  1294.            exit;
  1295.          { Noch Zeichen im Buffer? ansonsten laden }
  1296.          if f.bufpos>=f.bufend then
  1297.            dateifunc(f.inoutfunc)(f);
  1298.          while f.buffer[f.bufpos]<>#10 do
  1299.            begin
  1300.               { trotz Laden nichts im Buffer ? }
  1301.               if f.bufpos>=f.bufend then
  1302.                 { dann vergiss' s }
  1303.                 exit;
  1304.               inc(f.bufpos);
  1305.               if f.bufpos>=f.bufend then
  1306.                 dateifunc(f.inoutfunc)(f);
  1307.            end;
  1308.          inc(f.bufpos);
  1309.       end;
  1310.  
  1311.     procedure r(var f : textrec;var s : string);[public,alias: 'READ_TEXT_STRING'];
  1312.  
  1313.       begin
  1314.          { the file must be opened for input }
  1315.          if f.mode<>fminput then
  1316.            exit;
  1317.          { delete the string }
  1318.          s:='';
  1319.          { Noch Zeichen im Buffer? ansonsten Laden }
  1320.          if f.bufpos>=f.bufend then
  1321.            dateifunc(f.inoutfunc)(f);
  1322.  
  1323.          while f.buffer[f.bufpos]<>#10 do
  1324.            begin
  1325.               { if no chars in the buffer, then forget this }
  1326.               if f.bufpos>=f.bufend then
  1327.                 exit;
  1328.               if f.buffer[f.bufpos]<>#13 then
  1329.                 s:=s+f.buffer[f.bufpos];
  1330.               inc(f.bufpos);
  1331.               if f.bufpos>=f.bufend then
  1332.                 dateifunc(f.inoutfunc)(f);
  1333.            end;
  1334.       end;
  1335.  
  1336.     procedure r(var f : textrec;var l : longint);[public,alias: 'READ_TEXT_LONGINT'];
  1337.  
  1338.       var
  1339.          hs : string;
  1340.          code : word;
  1341.  
  1342.       label
  1343.          ready;
  1344.  
  1345.       begin
  1346.          if f.mode<>fminput then
  1347.            exit;
  1348.          { del the number }
  1349.          l:=0;
  1350.          { clear the string }
  1351.          hs:='';
  1352.          { Noch Zeichen im Buffer? ansonsten Laden }
  1353.          if f.bufpos>=f.bufend then
  1354.            dateifunc(f.inoutfunc)(f);
  1355.          { ignore spaces }
  1356.          while (f.buffer[f.bufpos]=#13) or
  1357.                (f.buffer[f.bufpos]=#10) or
  1358.                (f.buffer[f.bufpos]=#9) or
  1359.                (f.buffer[f.bufpos]=' ') do
  1360.            begin
  1361.               { if no chars in the buffer, then forget this }
  1362.               if f.bufpos>=f.bufend then
  1363.                 exit;
  1364.               inc(f.bufpos);
  1365.               if f.bufpos>=f.bufend then
  1366.                 dateifunc(f.inoutfunc)(f);
  1367.            end;
  1368.          { read the sign }
  1369.          if (f.buffer[f.bufpos]='-') or
  1370.             (f.buffer[f.bufpos]='+') then
  1371.            begin
  1372.               { if no chars in the buffer, then forget this }
  1373.               if f.bufpos>=f.bufend then
  1374.                 goto ready;
  1375.  
  1376.               hs:=hs+f.buffer[f.bufpos];
  1377.               inc(f.bufpos);
  1378.               if f.bufpos>=f.bufend then
  1379.                 dateifunc(f.inoutfunc)(f);
  1380.            end;
  1381.          while (ord(f.buffer[f.bufpos])>=ord('0')) and
  1382.            (ord(f.buffer[f.bufpos])<=ord('9')) do
  1383.            begin
  1384.               { if no chars in the buffer, then forget this }
  1385.               if f.bufpos>=f.bufend then
  1386.                 goto ready;
  1387.  
  1388.               hs:=hs+f.buffer[f.bufpos];
  1389.               inc(f.bufpos);
  1390.               if f.bufpos>=f.bufend then
  1391.                 dateifunc(f.inoutfunc)(f);
  1392.            end;
  1393.       ready:
  1394.          val(hs,l,code);
  1395.          if code<>0 then
  1396.            runerror(106);
  1397.       end;
  1398.  
  1399.     procedure r(var f : textrec;var l : integer);[public,alias:'READ_TEXT_INTEGER'];
  1400.  
  1401.       var
  1402.          v : longint;
  1403.          
  1404.       begin
  1405.          r(f,v);
  1406.          l:=v;
  1407.       end;
  1408.  
  1409.     procedure r(var f : textrec;var l : word);[public,alias:'READ_TEXT_WORD'];
  1410.  
  1411.       var
  1412.          v : longint;
  1413.          
  1414.       begin
  1415.          r(f,v);
  1416.          l:=v;
  1417.       end;
  1418.  
  1419.     procedure r(var f : textrec;var l : shortint);[public,alias:'READ_TEXT_SHORTINT'];
  1420.  
  1421.       var
  1422.          v : longint;
  1423.          
  1424.       begin
  1425.          r(f,v);
  1426.          l:=v;
  1427.       end;
  1428.  
  1429.     procedure r(var f : textrec;var l : byte);[public,alias:'READ_TEXT_BYTE'];
  1430.  
  1431.       var
  1432.          v : longint;
  1433.          
  1434.       begin
  1435.          r(f,v);
  1436.          l:=v;
  1437.       end;
  1438.     procedure r(var f : textrec;var c : char);[public,alias: 'READ_TEXT_CHAR'];
  1439.  
  1440.       var
  1441.          hs : string;
  1442.          code : word;
  1443.  
  1444.       begin
  1445.          c:=#0;
  1446.  
  1447.          { the file must be opened for input }
  1448.          if f.mode<>fminput then
  1449.            exit;
  1450.  
  1451.          { maybe reload }
  1452.          if f.bufpos>=f.bufend then
  1453.            dateifunc(f.inoutfunc)(f);
  1454.  
  1455.          if f.bufpos>=f.bufend then
  1456.            c:=#26
  1457.          else c:=f.buffer[f.bufpos];
  1458.  
  1459.          inc(f.bufpos);
  1460.       end;
  1461.  
  1462.     procedure r(var f : textrec;var d : double);[public,alias: 'READ_TEXT_REAL'];
  1463.  
  1464.       var
  1465.          hs : string;
  1466.          code : word;
  1467.  
  1468.       label
  1469.          ready;
  1470.  
  1471.       begin
  1472.          { f... long code }
  1473.          if f.mode<>fminput then
  1474.            exit;
  1475.          { del the number }
  1476.          d:=0.0;
  1477.          { clear the string }
  1478.          hs:='';
  1479.  
  1480.          { maybe reload }
  1481.          if f.bufpos>=f.bufend then
  1482.            dateifunc(f.inoutfunc)(f);
  1483.  
  1484.          { ignore spaces }
  1485.          while (f.buffer[f.bufpos]=#13) or
  1486.                (f.buffer[f.bufpos]=#10) or
  1487.                (f.buffer[f.bufpos]=#9) or
  1488.                (f.buffer[f.bufpos]=' ') do
  1489.            begin
  1490.               { if no chars in the buffer, then forget this }
  1491.               if f.bufpos>=f.bufend then
  1492.                 exit;
  1493.               inc(f.bufpos);
  1494.               if f.bufpos>=f.bufend then
  1495.                 dateifunc(f.inoutfunc)(f);
  1496.            end;
  1497.  
  1498.          { read the sign }
  1499.          if (f.buffer[f.bufpos]='-') or
  1500.             (f.buffer[f.bufpos]='+') then
  1501.            begin
  1502.               { if no chars in the buffer, then forget this }
  1503.               if f.bufpos>=f.bufend then
  1504.                 goto ready;
  1505.  
  1506.               hs:=hs+f.buffer[f.bufpos];
  1507.               inc(f.bufpos);
  1508.               if f.bufpos>=f.bufend then
  1509.                 dateifunc(f.inoutfunc)(f);
  1510.            end;
  1511.          while (ord(f.buffer[f.bufpos])>=ord('0')) and
  1512.            (ord(f.buffer[f.bufpos])<=ord('9')) do
  1513.            begin
  1514.               { if no chars in the buffer, then forget this }
  1515.               if f.bufpos>=f.bufend then
  1516.                 goto ready;
  1517.  
  1518.               hs:=hs+f.buffer[f.bufpos];
  1519.               inc(f.bufpos);
  1520.               if f.bufpos>=f.bufend then
  1521.                 dateifunc(f.inoutfunc)(f);
  1522.            end;
  1523.          { comma ? }
  1524.          if (f.buffer[f.bufpos]='.') then
  1525.            begin
  1526.               { if no chars in the buffer, then forget this }
  1527.               if f.bufpos>=f.bufend then
  1528.                 goto ready;
  1529.  
  1530.               hs:=hs+'.';
  1531.               inc(f.bufpos);
  1532.               if f.bufpos>=f.bufend then
  1533.                 dateifunc(f.inoutfunc)(f);
  1534.  
  1535.               while (ord(f.buffer[f.bufpos])>=ord('0')) and
  1536.                 (ord(f.buffer[f.bufpos])<=ord('9')) do
  1537.                 begin
  1538.                    { if no chars in the buffer, then forget this }
  1539.                    if f.bufpos>=f.bufend then
  1540.                      goto ready;
  1541.  
  1542.                    hs:=hs+f.buffer[f.bufpos];
  1543.                    inc(f.bufpos);
  1544.                    if f.bufpos>=f.bufend then
  1545.                      dateifunc(f.inoutfunc)(f);
  1546.                 end;
  1547.            end;
  1548.  
  1549.          { exponent ? }
  1550.          if (upcase(f.buffer[f.bufpos])='E') then
  1551.            begin
  1552.               { if no chars in the buffer, then forget this }
  1553.               if f.bufpos>=f.bufend then
  1554.                 goto ready;
  1555.  
  1556.               hs:=hs+'E';
  1557.               inc(f.bufpos);
  1558.               if f.bufpos>=f.bufend then
  1559.                 dateifunc(f.inoutfunc)(f);
  1560.  
  1561.               { read the sign of the exponent }
  1562.               if (f.buffer[f.bufpos]='-') or
  1563.                  (f.buffer[f.bufpos]='+') then
  1564.                 begin
  1565.                    { if no chars in the buffer, then forget this }
  1566.                    if f.bufpos>=f.bufend then
  1567.                      goto ready;
  1568.  
  1569.                    hs:=hs+f.buffer[f.bufpos];
  1570.                    inc(f.bufpos);
  1571.                    if f.bufpos>=f.bufend then
  1572.                      dateifunc(f.inoutfunc)(f);
  1573.                 end;
  1574.               while (ord(f.buffer[f.bufpos])>=ord('0')) and
  1575.                 (ord(f.buffer[f.bufpos])<=ord('9')) do
  1576.                 begin
  1577.                    { if no chars in the buffer, then forget this }
  1578.                    if f.bufpos>=f.bufend then
  1579.                      goto ready;
  1580.  
  1581.                    hs:=hs+f.buffer[f.bufpos];
  1582.                    inc(f.bufpos);
  1583.                    if f.bufpos>=f.bufend then
  1584.                      dateifunc(f.inoutfunc)(f);
  1585.                 end;
  1586.            end;
  1587.       ready:
  1588.          val(hs,d,code);
  1589.          if code<>0 then
  1590.            runerror(106);
  1591.       end;
  1592. {$ifndef VER0_6}
  1593.    procedure r(var f : textrec;var s : pchar);[public,alias:'READ_TEXT_PCHAR_AS_POINTER'];
  1594.  
  1595.       var p : pchar;
  1596.  
  1597.       begin
  1598.          { the file must be opened for input }
  1599.          if (f.mode<>fminput) or (s=nil) then
  1600.            exit;
  1601.          { delete the string }
  1602.          s^:=#0;
  1603.          p:=s;
  1604.          { if there are no more chars in the buffer then reload }
  1605.          if f.bufpos>=f.bufend then
  1606.            dateifunc(f.inoutfunc)(f);
  1607.          while f.buffer[f.bufpos]<>#10 do
  1608.            begin
  1609.               { if no chars in the buffer, then forget this }
  1610.               if f.bufpos>=f.bufend then
  1611.                 exit;
  1612.               if f.buffer[f.bufpos]<>#13 then
  1613.                 move (f.buffer[f.bufpos],p^,1);
  1614.               inc (longint(p));
  1615.               p^:=#0;
  1616.               inc(f.bufpos);
  1617.               if f.bufpos>=f.bufend then
  1618.                 dateifunc(f.inoutfunc)(f);
  1619.            end;
  1620.       end;
  1621.  
  1622.     procedure r(var f : textrec;var fi : fixed);[public,alias: 'READ_TEXT_FIXED'];
  1623.  
  1624.       var
  1625.          d : double;
  1626.  
  1627.          begin
  1628.         r(f,d);
  1629. {        longint(fi):=trunc(65536*d); }
  1630.          end;
  1631. {$endif VER0_6}
  1632.  
  1633.     function ioresult : word;
  1634.  
  1635.       begin
  1636.          ioresult:=inoutres;
  1637.          inoutres:=0;
  1638.       end;
  1639.  
  1640.     procedure blockread(var f : file;var buf;count : word;var result : word);[iocheck];
  1641.  
  1642.       var
  1643.          rl : longint;
  1644.  
  1645.       begin
  1646.          blockread(f,buf,count,rl);
  1647.          result:=rl;
  1648.       end;
  1649.  
  1650.     procedure w(var t : textrec);[public,alias: 'WRITELN_TEXT'];
  1651.  
  1652.       var
  1653.          hs : string;
  1654.  
  1655.       begin
  1656.          hs:=#13#10;
  1657.          w(0,t,hs);
  1658.       end;
  1659.  
  1660.     procedure close(var t : text);[public,alias: 'CLOSE_TEXT',iocheck];
  1661.  
  1662.       begin
  1663.          if (textrec(t).mode<>fmclosed) then
  1664.            begin
  1665.               dateifunc(textrec(t).flushfunc)(textrec(t));
  1666.               textrec(t).mode:=fmclosed;
  1667.               dateifunc(textrec(t).closefunc)(textrec(t));
  1668.            end;
  1669.       end;
  1670.  
  1671.     procedure initexception;[public,alias: 'INITEXCEPTION'];
  1672.  
  1673.       begin
  1674.          writeln('Exception während der Programminitialisierung aufgetreten');
  1675.          halt;
  1676.       end;
  1677.  
  1678.     function ptr(sel,off : word) : pointer;
  1679.  
  1680.       begin
  1681. {$ifdef DOS}
  1682.          ptr:=pointer($e0000000+sel shl 4+off);
  1683. {$else}
  1684.          ptr:=pointer(sel shl 4+off);
  1685. {$endif}
  1686.       end;
  1687.  
  1688.     function eof : boolean;
  1689.  
  1690.       begin
  1691.          eof:=eof(input);
  1692.       end;
  1693.  
  1694.     function eoln(var t : text) : boolean;
  1695.  
  1696.       begin
  1697.          { maybe we need new data }
  1698.          if textrec(t).bufpos>=textrec(t).bufend then
  1699.            dateifunc(textrec(t).inoutfunc)(textrec(t));
  1700.  
  1701.          eoln:=eof or
  1702.            (textrec(t).buffer[textrec(t).bufpos]=#13) or
  1703.            (textrec(t).buffer[textrec(t).bufpos]=#10);
  1704.       end;
  1705.  
  1706.     function eoln : boolean;
  1707.  
  1708.       begin
  1709.          eoln:=eoln(input);
  1710.       end;
  1711.  
  1712. {****************************************************************************
  1713.                     subroutines for string handling
  1714.  ****************************************************************************}
  1715.  
  1716.     function copy(const s : string;index : integer;count : byte): string;
  1717.  
  1718.        var
  1719.           i : longint;
  1720.  
  1721.        begin
  1722.           if count < 0 then count := 0;
  1723.           if index <= 0 then index := 1;
  1724.           if index <= ord(s[0]) then
  1725.             begin
  1726.                if count + index > ord(s[0]) then copy[0] := chr (ord(s[0]) - index +1)
  1727.                  else copy[0] := chr (count);
  1728.                for i := 1 to ord (s[0]) do copy[i] := s [index -1 + i];
  1729.             end
  1730.           else copy[0] := #0;
  1731.        end;
  1732.  
  1733.     procedure delete(var s : string;index : integer;count : integer);
  1734.  
  1735.        var i : longint;
  1736.  
  1737.        begin
  1738.           if index <= 0 then
  1739.             begin
  1740.                count := count + index -1;
  1741.                index := 1;
  1742.             end;
  1743.           if count <= 0 then exit;
  1744.           if ord (s[0]) >= index then
  1745.             begin
  1746.                if count + index > ord (s[0]) then count:= ord (s[0]) -index + 1;
  1747.                  for i := 0 to ord (s[0]) - (count+index) do
  1748.                    s [i+index] := s[i+count+index];
  1749.                s[0] := chr(ord (s[0]) - count);
  1750.             end;
  1751.        end;
  1752.  
  1753.     procedure insert(const source : string;var s : string;index : integer);
  1754.  
  1755.        var s3 : string;
  1756.  
  1757.        begin
  1758.           if index <= 0 then index := 1;
  1759.           s3 := copy (s, index, length(s));
  1760.           if index > length (s) then index := ord(s[0]) +1;
  1761.           s[0] := chr (index - 1);
  1762.           s := s + source + s3;
  1763.        end;
  1764.  
  1765.     function pos(const substr : string;const s : string): byte;
  1766.  
  1767.        var i : longint;
  1768.            j : byte;
  1769.            e : boolean;
  1770.  
  1771.        begin
  1772.           i := 0;
  1773.           j := 0;
  1774.           e := true;
  1775.           if substr = '' then e := false;
  1776.           while (e) and (i <= length (s) - length (substr)) do
  1777.             begin
  1778.                inc (i);
  1779.                if substr = copy (s,i,length (substr)) then
  1780.                  begin
  1781.                     j := i;
  1782.                     e := false;
  1783.                  end;
  1784.             end;
  1785.           pos := j;
  1786.        end;
  1787.  
  1788.     function upcase(c : char) : char;
  1789.  
  1790.        begin
  1791.           if (c >= #97) and (c <= #122) then c := chr(ord (c) - 32)
  1792.           else if (c >= #128) and (c <= #165) then
  1793.             case c of
  1794.                  #129 : c := #154;  {D}
  1795.                  #132 : c := #142;  {D}
  1796.                  #148 : c := #153;  {D}
  1797.                  #130 : c := #144;  {F}
  1798.                  #135 : c := #128;  {F}
  1799.                  #134 : c := #143;  {E}
  1800.                  #164 : c := #165;  {E}
  1801.             end;
  1802.           upcase := c;
  1803.        end;
  1804.  
  1805.     function upcase(const s : string) : string;
  1806.  
  1807.        var i : longint;
  1808.  
  1809.        begin
  1810.           upcase[0]:=s[0];
  1811.           for i := 1 to length (s) do 
  1812.             upcase[i] := upcase (s[i]);
  1813.        end;
  1814.  
  1815.     function lowercase(c : char) : char;
  1816.  
  1817.        begin
  1818.           if (c >= #65) and (c <= #90) then c := chr(ord (c) + 32)
  1819.           else if (c >= #128) and (c <= #165) then
  1820.             case c of
  1821.                  #154 : c := #129;  {D}
  1822.                  #142 : c := #132;  {D}
  1823.                  #153 : c := #148;  {D}
  1824.                  #144 : c := #130;  {F}
  1825.                  #128 : c := #135;  {F}
  1826.                  #143 : c := #134;  {E}
  1827.                  #165 : c := #164;  {E}
  1828.             end;
  1829.           lowercase := c;
  1830.        end;
  1831.  
  1832.     function lowercase(const s : string) : string;
  1833.  
  1834.       var i : longint;
  1835.  
  1836.       begin
  1837.          lowercase [0] := s[0];
  1838.          for i := 1 to length (s) do 
  1839.            lowercase[i] := lowercase (s[i]);
  1840.       end;
  1841.  
  1842.     function space (b : byte): string;
  1843.  
  1844.        var i : longint;
  1845.  
  1846.        begin
  1847.           space[0] := chr(b);
  1848.           for i := 1 to b do space[i] := #32;
  1849.        end;
  1850.  
  1851.     function hexstr(val : longint;cnt : byte) : string;
  1852.  
  1853.       const 
  1854.          hexval : string[16]=('0123456789ABCDEF');
  1855.          
  1856.       var 
  1857.          s : string;
  1858.          l2,i : integer;
  1859.          l1 : longInt;
  1860.          
  1861.       begin
  1862.          s[0]:=char(cnt);
  1863.          l1:=longint($f) shl (4*(cnt-1));
  1864.          for i:=1 to cnt do 
  1865.            begin
  1866.               l2:=(val and l1) shr (4*(cnt-i));
  1867.               l1:=l1 shr 4;
  1868.               s[i]:=hexval[l2+1];
  1869.            end;
  1870.          hexstr:=s;
  1871.       end;
  1872.  
  1873.     function binstr(val : longint;cnt : byte) : string;
  1874.  
  1875.       var
  1876.          s : string;
  1877.          mask,i : word;
  1878.  
  1879.       begin
  1880.          s[0]:=char(cnt);
  1881.          mask:=word(1) shl (cnt-1);
  1882.          for i:=1 to cnt do
  1883.            begin
  1884.               if (val and mask)<>0 then
  1885.                 s[i]:='1' else s[i]:='0';
  1886.               mask:=mask shr 1;
  1887.            end;
  1888.          binstr:=s;
  1889.       end;
  1890.     
  1891. { old version doesn't like this }
  1892. {$ifdef dummy}
  1893. {$ifndef VER0_6_5}
  1894. {$ifndef VER0_6_4}
  1895.     constructor tobject.create;
  1896.  
  1897.       begin
  1898.       end;
  1899.  
  1900.     destructor tobject.free;
  1901.  
  1902.       begin
  1903.       end;
  1904.  
  1905. {$endif}
  1906. {$endif}
  1907. {$endif}
  1908.